const co = require('co')
const URL = require('url')
const zlib = require('zlib')
const http = require('http')
const https = require('https')
const iconv = require('iconv-lite')
const querystring = require('querystring')

const hostname_charset = {};

module.exports.setCharset = function (hostname, charset) {
    hostname_charset[hostname] = charset;
};

module.exports.GET = function(url, headers) {
    return request('GET', url, headers)
}

module.exports.POST = function(url, headers, body) {
    return request('POST', url, headers, body)
}

function request(method, url, headers, body) {
    console.log(`Browser ${method} ${url}`)
    return function(cb) {
        // 默认请求头
        const options = URL.parse(url)
        options.method = method
        options.headers = {
            'Accept': '*/*',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',
            'Host': options.host,
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) enfi-cloud-desktop/2.4.0 Chrome/66.0.3359.181 Electron/3.1.8 Safari/537.36',
        }
        // 自定义请求头
        headers = headers || {}
        for (let k in headers) {
            options.headers[k] = headers[k]
        }
        // 请求体
        let postData = undefined
        if (typeof body === 'object') {
            if (options.headers['Content-Type'] && options.headers['Content-Type'].indexOf('json') !== -1) {
                postData = JSON.stringify(body)
                options.headers['Content-Type'] = 'application/json'
            } else {
                postData = querystring.stringify(body)
                options.headers['Content-Type'] = 'application/x-www-form-urlencoded'
            }
            options.headers['Content-Length'] = postData.length
        } else if (typeof body === 'string') {
            postData = body
            options.headers['Content-Length'] = postData.length
        }
        // 发起请求
        const HTTP = options.protocol === 'https:' ? https : http
        const req = HTTP.request(options, (res) => {
            res.setTimeout(3000)
            const data = []
            res.on('data', (chunk) => {
                data.push(chunk)
            })
            res.on('end', () => {
                co(function*() {
                    let buff
                    if (res.headers['content-encoding'] === 'gzip') { // Gzip supper
                        buff = yield gzip(Buffer.concat(data))
                    } else {
                        buff = Buffer.concat(data)
                    }
                    const charset = hostname_charset[options.hostname];
                    if (charset) {
                        buff = iconv.decode(buff, charset);
                    }
                    const body = buff.toString()
                    const ret = { code: res.statusCode, headers: res.headers, body: body }
                    if (res.headers['content-type'].indexOf('json') !== -1) {
                        ret.json = JSON.parse(body)
                    }
                    cb(null, ret)
                }).catch((err) => {
                    console.log('Browser err', err)
                    cb(null, { code: 500, headers: {}, body: '' })
                })
            })
        })
        req.setTimeout(3000)
        req.on('error', (err) => {
            console.log('Browser err', err)
            cb(null, { code: 500, headers: {}, body: '' })
        })
        if (postData) {
            req.write(postData)
        }
        req.end()
    }
}

function gzip(data) {
    return function(cb) {
        zlib.gunzip(data, function(err, decoded) {
            cb(err, decoded)
        })
    }
}